package carmadness.model;

import java.util.List;

/**
 * Járművet reprezentáló absztrakt osztály. Belőle származik a civil, a rendőr
 * és a bankrabló is.
 * 
 * @author Metzing Arpad
 * @version 1.0
 * @created 10-Apr-2010 2:32:43 PM
 */
public abstract class Vehicle implements IRuleVisitor, IVehicleVisitor
{

	/**
	 * A jármű alapértelmezett alapsúlya. Ennek és a szabályok által visszaadott
	 * faktoroknak segítségével számítható a forgalmi súly.
	 */
	protected float baseWeight;
	/**
	 * Erre áll vissza 0-ról, vagy ha már nincs lassítási kényszere.
	 */
	protected int defaultSpeed;
	/**
	 * A jármű aktuális sebessége (Segment/Tick mértékegységben)
	 */
	protected int speed;
	/**
	 * A lefékezett kocsi fékezés előtti sebessége
	 */
	protected int speedBeforeBrake;
	/**
	 * Amikor a jármű irányváltoztatási helyzetbe kerül, a döntési stratégia
	 * osztály dönti el, hogy melyik legyen a következő irány, amerre halad.
	 */
	protected Strategy strategy;
	/**
	 * Számított aktuális súly.
	 */
	protected float weight;
	/**
	 * A járművet tartalmazó csomagoló referenciája.
	 */
	protected VehicleWrapper wrapper;
	
	public Vehicle( Strategy _strategy )
	{
		this.strategy = _strategy;
		this.wrapper = new VehicleWrapper( this );
		this.speed = 5;
		this.speedBeforeBrake = 5;
	}
	
	/**
	 * Jármű Visitor minta szerinti accept metódusa. Alkalmazzuk a szabályok
	 * értékelésénél és az ütközéseknél.
	 * 
	 * @param visitor
	 *            Egy IRuleVisitor interfészt megvalósító objektum.
	 */
	public void accept( IVehicleVisitor visitor )
	{
		
	}

	/**
	 * A paraméterül kapott entryWeight fényében a stratégiájának megfelelően
	 * megváltoztatja a viselkedését. Ha továbbmegy a jármű, akkor a
	 * visszatérési érték <b>true</b>.
	 * 
	 * @param weight
	 *            A belépéshez szükséges súly.
	 */
	public boolean checkEntryWeight( float weight )
	{
		return false;
	}

	/**
	 * Ezen a metóduson keresztül kerül felszólításra a jármű arra, hogy
	 * válasszon haladási irányt.
	 * 
	 * @param directions
	 */
	public float chooseAngle( List<Float> directions )
	{
		return strategy.decide( directions );
	}

	/**
	 * A jármű aktuális haladási sebessége (Ticks/Sec), hogy az RS össze tudja
	 * állítani a szabálylistát.
	 */
	public float getSpeed()
	{
		return speed;
	}

	/**
	 * Ideiglenesen lefékezi a járművet, elmentve korábbi sebességét
	 * 
	 * @return boolean - le volt-e már eddig is fékezve a jármű?
	 */
	public boolean applyBrake()
	{
		if ( this.speed != 0f )
		{
			this.speedBeforeBrake = this.speed;
			this.speed = 0;
			return true;
		}
		
		return false;
	}
	
	/**
	 * Visszaállítja a jármű ideiglenes lefékezés előtti sebességét.
	 */
	public void releaseBrake() {
		this.speed = this.speedBeforeBrake;
	}

	/**
	 * A jármű teljes megsemmisítéséért felel.
	 */
	public void kill()
	{
		wrapper.kill();
		wrapper = null;
	}

	/**
	 * Beállítja a jármű járműcsomagolóját.
	 * 
	 * @param vw
	 */
	public void setWrapper( VehicleWrapper vw )
	{
		this.wrapper = vw;
	}

	/**
	 * A wrapper lekérése.
	 * 
	 * @return VehicleWrapper
	 */
	public VehicleWrapper getWrapper()
	{
		return wrapper;
	}

	/**
	 * Visszaadja a járművet vezérlő stratégia objektumot.
	 * 
	 * @return
	 */
	public Strategy getStrategy()
	{
		return strategy;
	}

	/**
	 * Az ütköző jármű típusától függő események elindítása.
	 * 
	 * @param vehicle
	 *            Civilian típusú jármű.
	 */
	public void visitVehicle( Civilian vehicle )
	{

	}

	/**
	 * Az ütköző jármű típusától függő események elindítása.
	 * 
	 * @param vehicle
	 *            Robber típusú jármű.
	 */
	public void visitVehicle( Robber vehicle )
	{

	}

	/**
	 * A Visitor minta szerinti visit metódus.
	 * 
	 * @param vehicle
	 *            Police típusú jármű.
	 */
	public void visitVehicle( Police vehicle )
	{

	}

	/**
	 * A Visitor minta szerinti visit metódus.
	 * 
	 * @param rule
	 *            SpeedLimit típusú Rule.
	 */
	public void visitRule( SpeedLimit rule )
	{

	}

	/**
	 * A Visitor minta szerinti visit metódus.
	 * 
	 * @param rule
	 *            TrafficLight típusú Rule.
	 */
	public void visitRule( TrafficLight rule )
	{

	}

	/**
	 * A Visitor minta szerinti visit metódus.
	 * 
	 * @param rule
	 *            StopSign típusú Rule.
	 */
	public void visitRule( StopSign rule )
	{

	}

	/**
	 * 
	 * @param bunny
	 */
	public void visitRule( Bunny bunny )
	{

	}

	/**
	 * Beállítja a jármű sebességét
	 * 
	 * @param value
	 *            A sebességérték
	 */
	public void setSpeed( int value )
	{
		speed = value;
		speedBeforeBrake = value;
	}

	/**
	 * Helyreállítja a jármű típus szerinti alapsúlyát. Szabályok alkalmazása
	 * előtt szükséges meghívni.
	 */
	public void resetWeight()
	{
		this.weight = this.baseWeight;
	}

	/**
	 * Megadja a jármű aktuálisan számított forgalmi súlyát.
	 * 
	 * @return float
	 */
	public float getWeight()
	{
		return this.weight;
	}
}
